/**
 * createStore(reducer,preloadedState,enhancer)
 * { getState,dispatch,subscribe }
 */

function createStore(reducer,preloadedState,enhancer){
  // 约束reducer参数类型
  if(typeof reducer !== 'function') throw new Error('reducer必须是函数')
  // 判断 enhancer 参数有没有传递
  if(typeof enhancer !=='undefined'){
    // 判断 enhancer 是不是一个函数
    if(typeof enhancer !== 'function'){
      throw new Error('enhancer必须是函数')
    }
    return enhancer(createStore)(reducer,preloadedState)
  }
  

  // store对象中存储的状态
  var currentState = preloadedState
  // 存放订阅者函数
  var currentListeners = []
  // 获取状态
  function getState(){
    return currentState
  }
  // 触发action
  function dispatch(action){
    // 判断action是否是对象
    if(!isPlainObject(action)) throw new Error('action必须是对象')
    if(typeof action.type === 'undefined') throw new Error('action对象中必须要有type属性')
    currentState = reducer(currentState, action)
    for(var i = 0; i < currentListeners.length; i++){
      // 获取订阅者
      var listener = currentListeners[i]
      // 调用订阅者
      listener()
    }
  }
  // 订阅状态
  function subscribe(listener){
    currentListeners.push(listener)
  }
  return {
    getState,
    dispatch,
    subscribe
  }
}

// 判断是否是对象
function isPlainObject(obj){
  // 排除基本类型和null
  if(typeof obj !== 'object'|| obj === null) return false
  // 区分数组和对象 原型对象对比方式
  var proto = obj
  while(Object.getPrototypeOf(proto)!==null){
    proto = Object.getPrototypeOf(proto)
  }
  return Object.getPrototypeOf(obj) === proto
}

function applyMiddleware(...middlewares){
  return function(createStore){
    return function(reducer,preloadedState){
      // 创建store
      var store = createStore(reducer, preloadedState)
      var middlewareAPI = {
        getState: store.getState,
        dispatch: store.dispatch
      }
      // 调用中间件的第一层函数 传递阉割版的store对象
      var chain = middlewares.map(middleware=> middleware(middlewareAPI))
      var dispatch = compose(...chain)(store.dispatch)
      return {
        ...store,
        dispatch
      }
    }
  }
}

function compose(){
  var funcs = [...arguments]
  return function(dispatch){
    for(var i = funcs.length-1;i>=0;i--){
      dispatch = funcs[i](dispatch)
    }
    return dispatch
  }
}

function bindActionCreators(actionCreators, dispatch){
  var boundActionCreators = {}
  for(var key in actionCreators){
    (function(key){
      boundActionCreators[key] = function(){
        dispatch(actionCreators[key]())
      }
    })(key)
  }
  return boundActionCreators
}

function combineReducers(reducers){
  // 检查reducers类型 它必须是函数
  var reducerKeys = Object.keys(reducers)
  for(var i = 0;i<reducerKeys.length;i++){
    var key = reducerKeys[i]
    if(typeof reducers[key] !== 'function') throw new Error('reducer必须是函数')
  }
  // 调用一个一个小的reducer 将每一个小的reducer中返回的状态存储在一个新的大的对象中
  return function(state,action){
    var nextState = {}
    for(var i = 0; i<reducerKeys.length; i++){
      var key = reducerKeys[i]
      var reducer = reducers[key]
      var previousStateForKey = satte[key]
      nextState[key] = reducer(previousStateForKey, action)
    }
    return nextState
  }
}